#include "basic_types.h"
#include "systemdata.h"

#define TEST
#ifdef TEST
int FlashEraseSystem(uint16 bk)
{
	memset(bk ?  SYSTEMDATA_FLASH_ADDR_B : SYSTEMDATA_FLASH_ADDR_A, 0xff, FMC_FLASH_SECTION_SIZE);
}
int FlashWriteSystemHead(uint16 bk)
{
	if(bk)
		*((uint16*)SYSTEMDATA_FLASH_ADDR_B) = *((uint16*)SYSTEMDATA_FLASH_ADDR_A) + 1;
	else
		*((uint16*)SYSTEMDATA_FLASH_ADDR_A) = *((uint16*)SYSTEMDATA_FLASH_ADDR_B) + 1;
	return 0;
}
int FlashWriteBuff(uint32 WriteAddr, uint8 *pBuffer,int32 NumToWrite)
{
	int i;
	int *dest = (int*)WriteAddr;
	int *src = (int*)pBuffer;
	for(i=0;i<NumToWrite; i+=4)
	{
		dest[i/4] = src[i/4];
	}
	return 0;
}
int FlashWriteSystem(uint16 bk, int offset, uint32 pBuffer, int len)
{
	void *dst = (void *)((bk ?  SYSTEMDATA_FLASH_ADDR_B : SYSTEMDATA_FLASH_ADDR_A) + offset);
	memcpy(dst, (void *)pBuffer, len);
	SYSTEM_DB_DEBUG("save to bk:%d offset:%d dst:%x",bk, offset, dst);
}
void debugSysData(S_SYSTEM_DATA * pSysData)
{
	printf("system:[\n");
	printf("\tversion:%s\n", pSysData->version);
	printf("\tbuildTime:%s\n", pSysData->buildTime);
	printf("\tmode:%d\n", pSysData->mode);
	printf("\tlcd:{%dx%d}\n", pSysData->lcd.width, pSysData->lcd.height);
	printf("\tid:%s\n", pSysData->id);
	printf("\tuart[%d]{%d, %d-%d-%d-%d }\n",0, pSysData->uart[0].port,
			pSysData->uart[0].baudRate, pSysData->uart[0].wordLength,
			pSysData->uart[0].stopBits,pSysData->uart[0].parity);
	printf("\tuart[%d]{%d, %d-%d-%d-%d}\n",1, pSysData->uart[1].port,
				pSysData->uart[1].baudRate, pSysData->uart[1].wordLength,
				pSysData->uart[1].stopBits, pSysData->uart[1].parity);
	printf("\tmaxPostion:%d\n", pSysData->maxPostion);
	printf("]\n");
}
#else
static int getSectorAndBanks(uint32 WriteAddr, uint32 *secnum, uint32 *banks)
{
	if(WriteAddr<0x8100000)
	{
		*banks = FLASH_BANK_1;
		*secnum = (WriteAddr-0x8000000)/FMC_FLASH_SECTION_SIZE;
	}
	else
	{
		*banks = FLASH_BANK_2;
		*secnum = (WriteAddr-0x8100000)/FMC_FLASH_SECTION_SIZE;
	}
	return 0;
}
int FlashWriteBuff(uint32 WriteAddr, uint8 *pBuffer,int32 NumToWrite)
{
	FLASH_EraseInitTypeDef FlashEraseInit;
	HAL_StatusTypeDef FlashStatus=HAL_OK;
	uint32 SectorError=0;
	uint32 endaddr=0;
	int result = 0;
	if(WriteAddr+NumToWrite >FMC_FLASH_END){
		return -1; //非法地址
	}
	HAL_FLASH_Unlock();             //解锁
	endaddr = WriteAddr+NumToWrite; 	//写入的结束地址
	FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;            //擦除类型，整页擦除
	getSectorAndBanks(WriteAddr, &FlashEraseInit.Sector, &FlashEraseInit.Banks);
	FlashEraseInit.NbSectors = 1;                                  //一次只擦除一个页
	if((result = HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError))!=HAL_OK)
	{
		SYSTEM_DB_DEBUG("Erase flash result is %d\n", result);
		return -1;
	}
	while(WriteAddr < endaddr)
	{
		FlashStatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, WriteAddr, (uint32)pBuffer);
		if(FlashStatus!=HAL_OK)//写入数据
		{
			result = -1;
			break; //写入异常
		}
		WriteAddr += 4 * sizeof(uint32);
		pBuffer += 4 * sizeof(uint32);
	}
	HAL_FLASH_Lock();           //上锁
	SYSTEM_DB_DEBUG("write flash result is %s\n", result == 0 ? "OK": "FAIL");
	return result;
}
int FlashEraseSystem(uint16 bk)
{
	FLASH_EraseInitTypeDef FlashEraseInit;
	uint32 SectorError=0;
	int result = 0;
	HAL_FLASH_Unlock(); 
	FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;            //擦除类型，整页擦除
	getSectorAndBanks( bk ? (SYSTEMDATA_FLASH_ADDR_B) : (SYSTEMDATA_FLASH_ADDR_A) , &FlashEraseInit.Sector, &FlashEraseInit.Banks);
	FlashEraseInit.NbSectors = 1;                                  //一次只擦除一个页
	if((result = HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError))!=HAL_OK)
	{
		SYSTEM_DB_DEBUG("Erase flash result is %d\n", result);
		HAL_FLASH_Lock(); 
		return -1;
	}
	HAL_FLASH_Lock(); 
	return 0;
}
int FlashWriteSystemHead(uint16 bk)
{
	uint32 WriteAddr = bk ? (SYSTEMDATA_FLASH_ADDR_B) : (SYSTEMDATA_FLASH_ADDR_A);
	uint16_t pBuffer = (bk ? *(uint16_t*) (SYSTEMDATA_FLASH_ADDR_B) :*(uint16_t*) (SYSTEMDATA_FLASH_ADDR_A)) + 1; 
	HAL_FLASH_Unlock(); 
	int result =  HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, WriteAddr, (uint32)&pBuffer);
	HAL_FLASH_Lock(); 
	return result;
}
int FlashWriteSystem(uint16 bk, int offset, uint32 pBuffer, int len)
{
	int FlashStatus = 0, result = 0;
	uint32 WriteAddr = (bk ? (SYSTEMDATA_FLASH_ADDR_B) : (SYSTEMDATA_FLASH_ADDR_A)) + offset;
	HAL_FLASH_Unlock(); 
	while(WriteAddr < endaddr)
	{
		FlashStatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, WriteAddr, (uint32)pBuffer);
		if(FlashStatus!=HAL_OK)//写入数据
		{
			result = -1;
			break; //写入异常
		}
		WriteAddr += 4 * sizeof(uint32);
		pBuffer += 4 * sizeof(uint32);
	}
	HAL_FLASH_Lock(); 
	return result;
}
#endif
